package com.pll.util;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.ocr_api20210707.Client;
import com.aliyun.ocr_api20210707.models.RecognizeIdcardRequest;
import com.aliyun.ocr_api20210707.models.RecognizeIdcardResponse;
import com.aliyun.teautil.models.RuntimeOptions;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * OCR文字识别工具类
 * 提供身份证和营业执照的OCR识别功能
 * 支持从输入流和网络URL读取图片
 */
public class OcrUtil {

    // 营业执照OCR接口配置
    private static final String BUSINESS_LICENSE_HOST = "https://bizlicense.market.alicloudapi.com";
    private static final String BUSINESS_LICENSE_PATH = "/rest/160601/ocr/ocr_business_license.json";
    private static final String APP_CODE = "1c396eacc15f40bb822b4d27b31c872d";

    /**
     * 识别营业执照并返回关键信息（支持输入流）
     * @param imageStream 图片输入流
     * @return 包含注册号(regNum)和法人(person)的Map
     * @throws IOException 图片读取或API调用异常
     */
    public static Map<String, String> recognizeBusinessLicense(InputStream imageStream) throws IOException {
        // 从输入流读取图片并转换为Base64
        String base64Image = encodeImageToBase64(imageStream);
        return doRecognizeBusinessLicense(base64Image);
    }

    /**
     * 识别营业执照并返回关键信息（支持URL）
     * @param imageUrl 图片URL
     * @return 包含注册号(regNum)和法人(person)的Map
     * @throws IOException 图片读取或API调用异常
     */
    public static Map<String, String> recognizeBusinessLicense(String imageUrl) throws IOException {
        // 验证URL格式
        if (!imageUrl.startsWith("http://") && !imageUrl.startsWith("https://")) {
            throw new IllegalArgumentException("无效的URL格式，必须以http://或https://开头");
        }
        // 从URL读取图片并转换为Base64
        String base64Image = encodeImageToBase64(imageUrl);
        return doRecognizeBusinessLicense(base64Image);
    }

    /**
     * 执行营业执照OCR识别的核心逻辑
     */
    private static Map<String, String> doRecognizeBusinessLicense(String base64Image) throws IOException {
        // 构造请求头
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "APPCODE " + APP_CODE);
        headers.put("Content-Type", "application/json; charset=UTF-8");

        // 构造请求体
        String requestBody = "{\"image\":\"" + base64Image + "\"}";

        try {
            // 发送请求
            HttpResponse response = HttpUtils.doPost(
                    BUSINESS_LICENSE_HOST,
                    BUSINESS_LICENSE_PATH,
                    "POST",
                    headers,
                    new HashMap<>(),
                    requestBody
            );

            // 检查响应状态
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                String errorContent = EntityUtils.toString(response.getEntity());
                throw new IOException("营业执照OCR识别失败，状态码: " + statusCode + ", 响应内容: " + errorContent);
            }

            // 解析响应JSON
            String jsonResult = EntityUtils.toString(response.getEntity());
            return parseBusinessLicenseResult(jsonResult);
        } catch (Exception e) {
            throw new IOException("调用营业执照OCR接口失败: " + e.getMessage(), e);
        }
    }

    /**
     * 解析营业执照OCR返回的JSON结果
     */
    private static Map<String, String> parseBusinessLicenseResult(String jsonResult) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        @SuppressWarnings("unchecked")
        Map<String, Object> resultMap = mapper.readValue(jsonResult, Map.class);

        Map<String, String> extractedInfo = new HashMap<>();
        // 提取注册号（字段可能需要根据实际API响应调整）
        extractedInfo.put("regNum", (String) resultMap.get("reg_num"));
        // 提取法人信息（字段可能需要根据实际API响应调整）
        extractedInfo.put("person", (String) resultMap.get("person"));

        return extractedInfo;
    }

    /**
     * 身份证识别（支持输入流）
     * @param imageStream 身份证图片输入流
     * @return 包含姓名(name)和身份证号(idNumber)的Map，识别失败时包含error字段
     */
    public static Map<String, String> idCardRecognition(InputStream imageStream) {
        Map<String, String> result = new HashMap<>();

        try {
            // 创建客户端
            Client client = Sample.createClient();

            // 创建请求对象
            RecognizeIdcardRequest request = new RecognizeIdcardRequest();
            request.body = imageStream;  // 设置请求体为输入流

            // 调用OCR接口
            RuntimeOptions runtime = new RuntimeOptions();
            RecognizeIdcardResponse response = client.recognizeIdcardWithOptions(request, runtime);

            // 解析响应
            JSONObject data = JSONObject.parseObject(response.body.data)
                    .getJSONObject("data")
                    .getJSONObject("face")
                    .getJSONObject("data");

            result.put("name", data.getString("name"));
            result.put("idNumber", data.getString("idNumber"));

        } catch (Exception e) {
            result.put("error", "身份证识别失败: " + e.getMessage());
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 将输入流转换为Base64编码
     */
    private static String encodeImageToBase64(InputStream imageStream) throws IOException {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = imageStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            return Base64.getEncoder().encodeToString(outputStream.toByteArray());
        }
    }

    /**
     * 将URL图片转换为Base64编码
     */
    private static String encodeImageToBase64(String imageUrl) throws IOException {
        try (InputStream inputStream = new URL(imageUrl).openStream()) {
            return encodeImageToBase64(inputStream);
        }
    }
}